{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "59c0fbea-9eda-4477-be6c-32647cef1ec7",
   "metadata": {},
   "source": [
    "# CI Simulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "06090a72-1365-43de-9c37-35c4c4e2f3c4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Author: Sebastian Raschka\n",
      "\n",
      "Python implementation: CPython\n",
      "Python version       : 3.10.6\n",
      "IPython version      : 8.12.0\n",
      "\n",
      "numpy     : 1.23.5\n",
      "mlxtend   : 0.22.0\n",
      "matplotlib: 3.7.1\n",
      "sklearn   : 1.2.2\n",
      "\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p numpy,mlxtend,matplotlib,sklearn"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12618aaa-7980-4ed3-8cd8-cd7ce3d3809a",
   "metadata": {},
   "source": [
    "- This notebook supplements the [1_four-methods](1_four-methods) with a simulated case study.\n",
    "\n",
    "- Here, we are interested in seeing whether the true model accuracy (generalization accuracy) is actually contained in the confidence intervals.\n",
    "\n",
    "- For this, we create a synthetic dataset consisting of 10 million and 2 thousand data points for classification as shown in the next section."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8412450-153d-4788-89ed-0e5caa6e7b7b",
   "metadata": {},
   "source": [
    "## Large Synthetic Training and Test Sets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "91d86525-404f-4c82-80b5-38eafc26955f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.datasets import make_classification\n",
    "\n",
    "X, y = make_classification(\n",
    "    n_samples=10_002_000,\n",
    "    n_features=12,\n",
    "    n_redundant=5,\n",
    "    n_classes=2,\n",
    "    random_state=123,\n",
    "    flip_y=0.25,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "fd6fb5cc-24d1-47bd-8682-f4fd25f1eda4",
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train = X[:1_000]\n",
    "y_train = y[:1_000]\n",
    "\n",
    "X_test = X[1_000:2_000]\n",
    "y_test = y[1_000:2_000]\n",
    "\n",
    "X_huge_test = X[2_000:]\n",
    "y_huge_test = y[2_000:]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c018df3-637b-41bd-b270-4935527fff94",
   "metadata": {},
   "source": [
    "- Note that the 1000 data points are used for training, the second 1000 data points are used for testing, and the remaining 10,000,000 data points represent the dataset we use to calculate the true performance of the model."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a391f1e1-d3ab-45fe-81ee-bf5a48600afd",
   "metadata": {},
   "source": [
    "## True Generalization Performance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7ce712bf-e9ba-4764-a3af-e03e1261939b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7882329"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.neural_network import MLPClassifier\n",
    "\n",
    "\n",
    "clf = MLPClassifier(\n",
    "    hidden_layer_sizes=(10,),\n",
    "    activation=\"relu\",\n",
    "    learning_rate_init=0.01,\n",
    "    random_state=123,\n",
    "    solver=\"adam\",\n",
    "    max_iter=500\n",
    ")\n",
    "\n",
    "clf.fit(X_train, y_train)\n",
    "\n",
    "acc_test_true = clf.score(X_huge_test, y_huge_test)\n",
    "acc_test_true"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68a4eee6-2422-4b9d-9d89-a7ffef36d730",
   "metadata": {},
   "source": [
    "## 1) Normal Approximation Interval Based on the Test Set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "98aad95f-e372-4766-9912-5828f2f83720",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7720698282384794 0.8219301717615207\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import scipy.stats\n",
    "\n",
    "confidence = 0.95  # Change to your desired confidence level\n",
    "z_value = scipy.stats.norm.ppf((1 + confidence) / 2.0)\n",
    "\n",
    "\n",
    "clf.fit(X_train, y_train)\n",
    "\n",
    "acc_test = clf.score(X_test, y_test)\n",
    "ci_length = z_value * np.sqrt((acc_test * (1 - acc_test)) / y_test.shape[0])\n",
    "\n",
    "ci_lower = acc_test - ci_length\n",
    "ci_upper = acc_test + ci_length\n",
    "\n",
    "print(ci_lower, ci_upper)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9a7f37e8-2bf5-447f-be9c-9306c6881a60",
   "metadata": {},
   "outputs": [],
   "source": [
    "results = {\n",
    "    \"Method 1: Normal approximation\": {\n",
    "        \"Test accuracy\": acc_test,\n",
    "        \"Lower 95% CI\": ci_lower,\n",
    "        \"Upper 95% CI\": ci_upper,\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93d20746-5386-45b1-96cb-7c8d43fc2aa6",
   "metadata": {},
   "source": [
    "## 2) Bootstrapping Training Sets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4539dd53-3974-4978-9d6c-8bc9991b7b9a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.769659240981034"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "rng = np.random.RandomState(seed=12345)\n",
    "idx = np.arange(y_train.shape[0])\n",
    "\n",
    "bootstrap_train_accuracies = []\n",
    "bootstrap_rounds = 200\n",
    "\n",
    "\n",
    "for i in range(bootstrap_rounds):\n",
    "\n",
    "    train_idx = rng.choice(idx, size=idx.shape[0], replace=True)\n",
    "    valid_idx = np.setdiff1d(idx, train_idx, assume_unique=False)\n",
    "\n",
    "    boot_train_X, boot_train_y = X_train[train_idx], y_train[train_idx]\n",
    "    boot_valid_X, boot_valid_y = X_train[valid_idx], y_train[valid_idx]\n",
    "\n",
    "    clf.fit(boot_train_X, boot_train_y)\n",
    "    acc = clf.score(boot_valid_X, boot_valid_y)\n",
    "    bootstrap_train_accuracies.append(acc)\n",
    "\n",
    "bootstrap_train_mean = np.mean(bootstrap_train_accuracies)\n",
    "bootstrap_train_mean"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67a3827e-6b5a-49fe-bb82-6819d2f71dea",
   "metadata": {},
   "source": [
    "- We can visualize the test accuracies from bootstrapping ($ \\text{ACC}_{\\text{boot}, j}$) along with their sample mean ($\\text{ACC}_{\\text{bootavg}}$) in a historgram:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "116785aa-ced2-4931-8749-bc568be9f174",
   "metadata": {},
   "source": [
    "#### Using the Percentile Method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "dffef535-c33a-4450-a014-91a36b984143",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7280214285714285 0.8092909569699687\n"
     ]
    }
   ],
   "source": [
    "ci_lower = np.percentile(bootstrap_train_accuracies, 2.5)\n",
    "ci_upper = np.percentile(bootstrap_train_accuracies, 97.5)\n",
    "\n",
    "print(ci_lower, ci_upper)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f083f9f3-baf6-46d1-a164-55af52ffe172",
   "metadata": {},
   "source": [
    "- Let's have a look how it looks like in the context of our "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "775e8291-79f4-4dfb-a5cb-229340d17c20",
   "metadata": {},
   "outputs": [],
   "source": [
    "results[\"Method 2: Bootstrap, percentile\"] = {\n",
    "    \"Test accuracy\": bootstrap_train_mean,\n",
    "    \"Lower 95% CI\": ci_lower,\n",
    "    \"Upper 95% CI\": ci_upper,\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd71a1de-ab21-482a-8618-bfca8eac0f75",
   "metadata": {},
   "source": [
    "## 3) Bootstrapping the Test Set Predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "2f8f89de-4b18-40bc-91bc-3159031681ee",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7963800000000001"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clf.fit(X_train, y_train)\n",
    "\n",
    "predictions_test = clf.predict(X_test)\n",
    "acc_test = np.mean(predictions_test == y_test)\n",
    "\n",
    "rng = np.random.RandomState(seed=12345)\n",
    "idx = np.arange(y_test.shape[0])\n",
    "\n",
    "test_accuracies = []\n",
    "\n",
    "for i in range(200):\n",
    "\n",
    "    pred_idx = rng.choice(idx, size=idx.shape[0], replace=True)\n",
    "    acc_test_boot = np.mean(predictions_test[pred_idx] == y_test[pred_idx])\n",
    "    test_accuracies.append(acc_test_boot)\n",
    "\n",
    "bootstrap_train_mean = np.mean(test_accuracies)\n",
    "bootstrap_train_mean"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36320135-7ab7-4ec5-9583-6354f9e6f130",
   "metadata": {},
   "source": [
    "- We can then use the familiar percentile approach to get the confidence interval:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a605c0b8-5a6a-4ee1-b77c-ad1224a26da4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.768 0.825\n"
     ]
    }
   ],
   "source": [
    "ci_lower = np.percentile(test_accuracies, 2.5)\n",
    "ci_upper = np.percentile(test_accuracies, 97.5)\n",
    "\n",
    "print(ci_lower, ci_upper)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "2f392400-0ccb-47af-9932-8131739a317f",
   "metadata": {},
   "outputs": [],
   "source": [
    "results[\"Method 3: Bootstrap test set\"] = {\n",
    "    \"Test accuracy\": bootstrap_train_mean,\n",
    "    \"Lower 95% CI\": ci_lower,\n",
    "    \"Upper 95% CI\": ci_upper,\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb9ec28a-f43e-4f6c-a5b5-741deff5a49a",
   "metadata": {},
   "source": [
    "## 4) Confidence Intervals from Retraining Models with Different Random Seeds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8cd8706e-5066-4ff9-bb87-23c7817a1993",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7934"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_accuracies = []\n",
    "rounds = 5\n",
    "\n",
    "\n",
    "for i in range(rounds):\n",
    "    \n",
    "    clf = MLPClassifier(\n",
    "        hidden_layer_sizes=(10,),\n",
    "        activation=\"relu\",\n",
    "        learning_rate_init=0.01,\n",
    "        random_state=i,  # only change random seed here\n",
    "        solver=\"adam\",\n",
    "        max_iter=500\n",
    ")\n",
    "\n",
    "    clf.fit(X_train, y_train)\n",
    "    acc = clf.score(X_test, y_test)\n",
    "    test_accuracies.append(acc)\n",
    "\n",
    "test_mean = np.mean(test_accuracies)\n",
    "test_mean"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "45635b69-acfa-4028-86cc-393d12f50e32",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7838787766707844 0.8029212233292156\n"
     ]
    }
   ],
   "source": [
    "confidence = 0.95  # Change to your desired confidence level\n",
    "t_value = scipy.stats.t.ppf((1 + confidence) / 2.0, df=rounds - 1)\n",
    "\n",
    "sd = np.std(test_accuracies, ddof=1)\n",
    "se = sd / np.sqrt(rounds)\n",
    "\n",
    "ci_length = t_value * se\n",
    "\n",
    "ci_lower = test_mean - ci_length\n",
    "ci_upper = test_mean + ci_length\n",
    "\n",
    "print(ci_lower, ci_upper)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "46661c99-4f4f-4dc1-88df-666d8b3aa8f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "results[\"Method 4: Random seeds\"] = {\n",
    "    \"Test accuracy\": test_mean,\n",
    "    \"Lower 95% CI\": ci_lower,\n",
    "    \"Upper 95% CI\": ci_upper,\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb4ec325-61b9-4862-acf4-0bfa523d228d",
   "metadata": {},
   "source": [
    "## Comparison"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "3be3ae62-a57d-4183-bcf4-b80593e1f7e2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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m5srwsLChL29vdDW1hZWVlaiX79+4ueff5bqjB07VpiZmQkAIjw8vNzjLJaeni4AiAcPHlSq/psgNzdX7N69W+Tm5tZ2V6pHZqYQQNHPc+/z0uQXFIrTSQ/E7iu3xemkByK/oFAI8RrGpBowJqoYE1WMSekePHggAIj09PQa3Y9MCFHalCmiV97Ro0fh5+eHR48e8RuvypGRkQFjY2M8ePCAN3v9T15eHvbv34+AgIDXY07b06dA8RWlzEyVm70q47WLSTVgTFQxJqoYk9I9fPgQ5ubmSE9Ph5GRUY3tRy3nyBIRERERMZElIiIiIrWkljd7EQFFXw3LmTFERERvLo7IEhEREZFaYiJLRERERGqJiSwRERERqSUmskRERESklpjIEhEREZFaYiJLRERERGqJiSwRERERqSUmskRERESklpjIEhEREZFaYiJLRERERGqJiSwRERERqSUmskRERESklpjIEhEREZFaYiJLRERERGqJiSwRERERqSUmskRERESklpjIEhEREZFaYiJLRERERGqJiSwRERERqSUmskRERESklpjIEhEREZFaYiJLRERERGpJbRPZTp06YdKkSdXe7ty5c9G8efNqb5eoNNHR0TAxMZGWef4RERFVXrUnskFBQZDJZBg7dqzKunHjxkEmkyEoKKjS7R09ehQymQyPHz+uvk7+Az/99BMGDRoEGxsbKBQKuLi4YOXKlVVup/i4in8UCgXc3Nzw3//+t9r7XNWkPzU1FTKZDFevXq32vrzJ7O3tsWLFCqWygQMH4saNG7XTIapxBYUCZ5If4rurf+BM8kMUFIra7hIR0WtFqyYatbGxQUxMDD777DMoFAoAQHZ2NrZt2wZbW9ua2OVLc+nSJVhYWGDLli2wsbHB6dOn8f7770NTUxPjx4+vcnuJiYkwMjJCVlYWvv/+e4SEhKBhw4bo0qVLDfS+euXm5kJHR6e2u/GPCCFQUFAALa0aeStUSKFQSO8Rer0c+PUO5n0fjzvp2VKZtbEuwvu4okdT61rsGRHR66NGpha0aNECtra22Llzp1S2c+dO2NjYwNPTU6muEAJLly6Fo6MjFAoFPDw88O233wIoGhn08/MDANSpU0dlNLewsBChoaEwNTWFlZUV5s6dq9R2WloaAgMDYWBgACMjIwwYMAB//fWXUp2IiAjUrVsXhoaGGDlyJLKz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",
      "text/plain": [
       "<Figure size 700x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "labels = list(results.keys())\n",
    "\n",
    "means = np.array([results[k][\"Test accuracy\"] for k in labels])\n",
    "lower_error = np.array([results[k][\"Lower 95% CI\"] for k in labels])\n",
    "upper_error = np.array([results[k][\"Upper 95% CI\"] for k in labels])\n",
    "\n",
    "asymmetric_error = [means - lower_error, upper_error - means]\n",
    "\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7, 3))\n",
    "ax.errorbar(means, np.arange(len(means)), xerr=asymmetric_error, fmt=\"o\")\n",
    "ax.set_xlim([0.7, 1.0])\n",
    "ax.set_yticks(np.arange(len(means)))\n",
    "ax.set_yticklabels(labels)\n",
    "ax.set_xlabel(\"Prediction accuracy\")\n",
    "ax.set_title(\"95% confidence intervals\")\n",
    "\n",
    "ax.vlines(acc_test_true, [0], 5, lw=1.5, color=\"red\", linestyle=\"-\", label=\"True value\")\n",
    "\n",
    "plt.grid()\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
